package com.newlink.building.common_base.utils

import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.net.wifi.WifiManager
import android.os.Build
import kotlinx.coroutines.*
import java.io.IOException
import java.net.*
import java.util.concurrent.TimeUnit

/**
 * 增强版网络工具类
 * @Author: Enhanced by Claude
 * @Date: 2025-09-15
 * @Description: 现代化的网络状态检测和管理工具
 */
object NetworkUtilsEnhanced {

    private const val PING_TIMEOUT = 3000L
    private const val HTTP_TIMEOUT = 5000L

    /**
     * 网络类型枚举
     */
    enum class NetworkType {
        NONE, WIFI, MOBILE, ETHERNET, VPN, OTHER
    }

    /**
     * 网络连接状态数据类
     */
    data class NetworkStatus(
        val isConnected: Boolean,
        val networkType: NetworkType,
        val connectionSpeed: ConnectionSpeed,
        val ssid: String? = null,  // WiFi 名称
        val signalStrength: Int = -1,  // 信号强度
        val ipAddress: String? = null,
        val isMetered: Boolean = false,  // 是否计费网络
        val linkDownstreamBandwidthKbps: Int = -1,
        val linkUpstreamBandwidthKbps: Int = -1
    )

    /**
     * 连接速度枚举
     */
    enum class ConnectionSpeed {
        UNKNOWN, SLOW, MEDIUM, FAST, VERY_FAST
    }

    /**
     * 网络监听器接口
     */
    interface NetworkStatusListener {
        fun onNetworkAvailable(networkStatus: NetworkStatus)
        fun onNetworkLost()
        fun onNetworkChanged(networkStatus: NetworkStatus)
    }

    // ========== 网络状态检测 ==========

    /**
     * 检查网络是否可用（兼容新旧API）
     */
    fun isNetworkAvailable(context: Context): Boolean {
        return try {
            val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                val network = connectivityManager.activeNetwork ?: return false
                val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
                capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
                capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
            } else {
                @Suppress("DEPRECATION")
                val networkInfo = connectivityManager.activeNetworkInfo
                networkInfo?.isConnected == true
            }
        } catch (e: Exception) {
            EnhancedLogger.e("NetworkUtils", "检查网络可用性失败", e)
            false
        }
    }

    /**
     * 获取当前网络类型
     */
    fun getCurrentNetworkType(context: Context): NetworkType {
        return try {
            val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                val network = connectivityManager.activeNetwork ?: return NetworkType.NONE
                val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return NetworkType.NONE

                when {
                    capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> NetworkType.WIFI
                    capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> NetworkType.MOBILE
                    capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> NetworkType.ETHERNET
                    capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN) -> NetworkType.VPN
                    else -> NetworkType.OTHER
                }
            } else {
                @Suppress("DEPRECATION")
                val networkInfo = connectivityManager.activeNetworkInfo
                when (networkInfo?.type) {
                    ConnectivityManager.TYPE_WIFI -> NetworkType.WIFI
                    ConnectivityManager.TYPE_MOBILE -> NetworkType.MOBILE
                    ConnectivityManager.TYPE_ETHERNET -> NetworkType.ETHERNET
                    ConnectivityManager.TYPE_VPN -> NetworkType.VPN
                    else -> if (networkInfo?.isConnected == true) NetworkType.OTHER else NetworkType.NONE
                }
            }
        } catch (e: Exception) {
            EnhancedLogger.e("NetworkUtils", "获取网络类型失败", e)
            NetworkType.NONE
        }
    }

    /**
     * 获取详细的网络状态
     */
    fun getNetworkStatus(context: Context): NetworkStatus {
        val isConnected = isNetworkAvailable(context)
        val networkType = getCurrentNetworkType(context)
        val connectionSpeed = getConnectionSpeed(context)
        val ipAddress = getLocalIpAddress()

        var ssid: String? = null
        var signalStrength = -1
        var isMetered = false
        var linkDownstreamBandwidthKbps = -1
        var linkUpstreamBandwidthKbps = -1

        try {
            val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                val network = connectivityManager.activeNetwork
                val capabilities = connectivityManager.getNetworkCapabilities(network)

                capabilities?.let {
                    isMetered = !it.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
                    linkDownstreamBandwidthKbps = it.linkDownstreamBandwidthKbps
                    linkUpstreamBandwidthKbps = it.linkUpstreamBandwidthKbps
                }
            }

            // 获取 WiFi 详细信息
            if (networkType == NetworkType.WIFI) {
                val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
                val wifiInfo = wifiManager.connectionInfo
                ssid = wifiInfo.ssid?.replace("\"", "")
                signalStrength = wifiInfo.rssi
            }
        } catch (e: Exception) {
            EnhancedLogger.e("NetworkUtils", "获取网络详细状态失败", e)
        }

        return NetworkStatus(
            isConnected = isConnected,
            networkType = networkType,
            connectionSpeed = connectionSpeed,
            ssid = ssid,
            signalStrength = signalStrength,
            ipAddress = ipAddress,
            isMetered = isMetered,
            linkDownstreamBandwidthKbps = linkDownstreamBandwidthKbps,
            linkUpstreamBandwidthKbps = linkUpstreamBandwidthKbps
        )
    }

    // ========== 连接质量检测 ==========

    /**
     * 获取连接速度等级
     */
    private fun getConnectionSpeed(context: Context): ConnectionSpeed {
        return try {
            val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                val network = connectivityManager.activeNetwork
                val capabilities = connectivityManager.getNetworkCapabilities(network)

                capabilities?.let {
                    val downstreamKbps = it.linkDownstreamBandwidthKbps
                    when {
                        downstreamKbps <= 0 -> ConnectionSpeed.UNKNOWN
                        downstreamKbps < 150 -> ConnectionSpeed.SLOW
                        downstreamKbps < 550 -> ConnectionSpeed.MEDIUM
                        downstreamKbps < 2000 -> ConnectionSpeed.FAST
                        else -> ConnectionSpeed.VERY_FAST
                    }
                } ?: ConnectionSpeed.UNKNOWN
            } else {
                // 对于旧版本，基于网络类型估算
                when (getCurrentNetworkType(context)) {
                    NetworkType.WIFI -> ConnectionSpeed.FAST
                    NetworkType.MOBILE -> ConnectionSpeed.MEDIUM
                    NetworkType.ETHERNET -> ConnectionSpeed.VERY_FAST
                    else -> ConnectionSpeed.UNKNOWN
                }
            }
        } catch (e: Exception) {
            EnhancedLogger.e("NetworkUtils", "获取连接速度失败", e)
            ConnectionSpeed.UNKNOWN
        }
    }

    /**
     * Ping测试网络延迟
     */
    suspend fun pingTest(host: String = "8.8.8.8", timeoutMs: Long = PING_TIMEOUT): Long = withContext(Dispatchers.IO) {
        return@withContext try {
            val startTime = System.currentTimeMillis()
            val address = InetAddress.getByName(host)
            val reachable = withTimeoutOrNull(timeoutMs) {
                address.isReachable(timeoutMs.toInt())
            }

            if (reachable == true) {
                System.currentTimeMillis() - startTime
            } else {
                -1L
            }
        } catch (e: Exception) {
            EnhancedLogger.e("NetworkUtils", "Ping测试失败: $host", e)
            -1L
        }
    }

    /**
     * HTTP连接测试
     */
    suspend fun httpConnectivityTest(url: String = "https://www.google.com", timeoutMs: Long = HTTP_TIMEOUT): Boolean = withContext(Dispatchers.IO) {
        return@withContext try {
            val connection = URL(url).openConnection() as HttpURLConnection
            connection.requestMethod = "HEAD"
            connection.connectTimeout = timeoutMs.toInt()
            connection.readTimeout = timeoutMs.toInt()
            connection.instanceFollowRedirects = false
            connection.useCaches = false

            val responseCode = connection.responseCode
            connection.disconnect()

            responseCode in 200..399
        } catch (e: Exception) {
            EnhancedLogger.e("NetworkUtils", "HTTP连接测试失败: $url", e)
            false
        }
    }

    // ========== IP地址获取 ==========

    /**
     * 获取本地IP地址
     */
    fun getLocalIpAddress(): String? {
        return try {
            val interfaces = NetworkInterface.getNetworkInterfaces()
            while (interfaces.hasMoreElements()) {
                val networkInterface = interfaces.nextElement()
                val addresses = networkInterface.inetAddresses

                while (addresses.hasMoreElements()) {
                    val address = addresses.nextElement()
                    if (!address.isLoopbackAddress && address is Inet4Address) {
                        return address.hostAddress
                    }
                }
            }
            null
        } catch (e: Exception) {
            EnhancedLogger.e("NetworkUtils", "获取本地IP地址失败", e)
            null
        }
    }

    /**
     * 获取公网IP地址
     */
    suspend fun getPublicIpAddress(): String? = withContext(Dispatchers.IO) {
        return@withContext try {
            val urls = listOf(
                "https://api.ipify.org",
                "https://icanhazip.com",
                "https://ifconfig.me/ip"
            )

            for (url in urls) {
                try {
                    val connection = URL(url).openConnection() as HttpURLConnection
                    connection.connectTimeout = HTTP_TIMEOUT.toInt()
                    connection.readTimeout = HTTP_TIMEOUT.toInt()

                    if (connection.responseCode == 200) {
                        val ip = connection.inputStream.bufferedReader().readText().trim()
                        connection.disconnect()
                        return@withContext ip
                    }
                    connection.disconnect()
                } catch (e: Exception) {
                    continue
                }
            }
            null
        } catch (e: Exception) {
            EnhancedLogger.e("NetworkUtils", "获取公网IP地址失败", e)
            null
        }
    }

    // ========== 网络监听 ==========

    /**
     * 网络状态监听器
     */
    class NetworkStatusMonitor(
        private val context: Context,
        private val listener: NetworkStatusListener
    ) {
        private var connectivityManager: ConnectivityManager? = null
        private var networkCallback: ConnectivityManager.NetworkCallback? = null

        fun startMonitoring() {
            try {
                connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    networkCallback = object : ConnectivityManager.NetworkCallback() {
                        override fun onAvailable(network: Network) {
                            super.onAvailable(network)
                            val status = getNetworkStatus(context)
                            listener.onNetworkAvailable(status)
                            EnhancedLogger.i("NetworkMonitor", "网络连接可用: ${status.networkType}")
                        }

                        override fun onLost(network: Network) {
                            super.onLost(network)
                            listener.onNetworkLost()
                            EnhancedLogger.w("NetworkMonitor", "网络连接丢失")
                        }

                        override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
                            super.onCapabilitiesChanged(network, networkCapabilities)
                            val status = getNetworkStatus(context)
                            listener.onNetworkChanged(status)
                            EnhancedLogger.i("NetworkMonitor", "网络状态变化: ${status.networkType}")
                        }
                    }

                    val request = NetworkRequest.Builder()
                        .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                        .build()

                    connectivityManager?.registerNetworkCallback(request, networkCallback!!)
                    EnhancedLogger.i("NetworkMonitor", "网络监听已启动")
                } else {
                    EnhancedLogger.w("NetworkMonitor", "当前系统版本不支持网络回调监听")
                }
            } catch (e: Exception) {
                EnhancedLogger.e("NetworkMonitor", "启动网络监听失败", e)
            }
        }

        fun stopMonitoring() {
            try {
                networkCallback?.let { callback ->
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        connectivityManager?.unregisterNetworkCallback(callback)
                    }
                }
                EnhancedLogger.i("NetworkMonitor", "网络监听已停止")
            } catch (e: Exception) {
                EnhancedLogger.e("NetworkMonitor", "停止网络监听失败", e)
            }
        }
    }

    // ========== 网络诊断 ==========

    /**
     * 执行网络诊断
     */
    suspend fun performNetworkDiagnosis(context: Context): NetworkDiagnosisResult = withContext(Dispatchers.IO) {
        val status = getNetworkStatus(context)
        val pingDelay = pingTest()
        val httpConnectivity = httpConnectivityTest()
        val publicIp = getPublicIpAddress()

        return@withContext NetworkDiagnosisResult(
            networkStatus = status,
            pingDelayMs = pingDelay,
            httpConnectivity = httpConnectivity,
            publicIpAddress = publicIp,
            timestamp = System.currentTimeMillis()
        )
    }

    /**
     * 网络诊断结果数据类
     */
    data class NetworkDiagnosisResult(
        val networkStatus: NetworkStatus,
        val pingDelayMs: Long,
        val httpConnectivity: Boolean,
        val publicIpAddress: String?,
        val timestamp: Long
    )

    /**
     * 记录网络诊断结果
     */
    fun logNetworkDiagnosis(result: NetworkDiagnosisResult) {
        val message = buildString {
            appendLine("🌐 网络诊断报告")
            appendLine("┌─────────────────────────────────────")
            appendLine("│ 连接状态: ${if (result.networkStatus.isConnected) "已连接" else "未连接"}")
            appendLine("│ 网络类型: ${result.networkStatus.networkType}")
            appendLine("│ 连接速度: ${result.networkStatus.connectionSpeed}")
            result.networkStatus.ssid?.let {
                appendLine("│ WiFi名称: $it")
            }
            result.networkStatus.ipAddress?.let {
                appendLine("│ 本地IP: $it")
            }
            result.publicIpAddress?.let {
                appendLine("│ 公网IP: $it")
            }
            appendLine("│ Ping延迟: ${if (result.pingDelayMs > 0) "${result.pingDelayMs}ms" else "超时"}")
            appendLine("│ HTTP连通性: ${if (result.httpConnectivity) "正常" else "异常"}")
            appendLine("│ 计费网络: ${if (result.networkStatus.isMetered) "是" else "否"}")
            if (result.networkStatus.linkDownstreamBandwidthKbps > 0) {
                appendLine("│ 下行带宽: ${result.networkStatus.linkDownstreamBandwidthKbps} Kbps")
            }
            if (result.networkStatus.linkUpstreamBandwidthKbps > 0) {
                appendLine("│ 上行带宽: ${result.networkStatus.linkUpstreamBandwidthKbps} Kbps")
            }
            append("└─────────────────────────────────────")
        }

        EnhancedLogger.i("NetworkDiagnosis", message)
    }
}